www.gusucode.com > VC++ 二进制文件浏览编辑器源代码-源码程序 > VC++ 二进制文件浏览编辑器源代码-源码程序\code\HexEditView.cpp

    //Download by http://www.NewXing.com
////////////////////////////////////////////////////////////////////////////
//	File:		HexEditView.cpp 
//	Version:	1.0.0.0
//	Created:	17-Oct-2003
//
//	Author:		Cuick
//	E-mail:		Cuick@163.net
//
//	You are free to use or modify this code .
////////////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "二进制编辑.h"
#include "HexEditView.h"
#include "二进制编辑Doc.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif


/////////////////////////////////////////////////////////////////////////////
// CHexEditView

IMPLEMENT_DYNCREATE(CHexEditView, CView)

CHexEditView::CHexEditView()
{
	m_text = NULL;
}

CHexEditView::~CHexEditView()
{
}


BEGIN_MESSAGE_MAP(CHexEditView, CView)
	//{{AFX_MSG_MAP(CHexEditView)
	ON_WM_SETFOCUS()
	ON_WM_KILLFOCUS()
	ON_WM_LBUTTONDOWN()
	ON_WM_LBUTTONUP()
	ON_WM_MOUSEMOVE()
	ON_WM_SIZE()
	ON_WM_MOUSEWHEEL()
	ON_WM_HSCROLL()
	ON_WM_VSCROLL()
	ON_WM_CHAR()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CHexEditView drawing

void CHexEditView::OnDraw(CDC* pDC)
{
	CRect rc;
	GetClientRect(rc);

	if(m_text == NULL)
	{
		pDC->FillRect(rc, &CBrush(RGB(255,255,255)));
		return;
	}
	

	CDC	dc;
	dc.CreateCompatibleDC(pDC);

	CBitmap bm;
	bm.CreateCompatibleBitmap(pDC, rc.Width(), rc.Height());
	dc.SelectObject(bm);
	dc.SetBoundsRect(&rc, DCB_DISABLE);

	CFont font;
	font.CreateFont ( m_LineHeight, 0, 0, 0, FW_NORMAL, 0, 0, 0, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN, 0 );
	CFont* oldFont = dc.SelectObject ( &font );

	CBrush bkBrush(RGB(255,255,255));
    dc.FillRect(rc, &bkBrush);
	
	UINT lineCY, lineCX;
	UINT dwPos;
	char currentchar[20];
	UCHAR text[17];

	int lineBeginPos;

	m_HexStart = m_CharWidth * (14 - m_LeftChar);	//计算二进制显示开始位置
	m_TextStart = m_HexStart + m_CharWidth * 50;	//计算ASCII码显示开始位置

	for(UINT i = 0; i < m_PageRows; i++)			//按行显示数据
	{
		lineBeginPos = (m_TopLine+i-1)*16;			//计算当前行开始字符相对于总缓冲区的位置
		lineCY = i * m_LineHeight;					//当前行的Y坐标
		sprintf(currentchar, "%08Xh:", lineBeginPos);

		dc.SetTextColor(::GetSysColor(COLOR_WINDOWTEXT));
		dc.SetBkColor(RGB(255,255,255));

		dc.TextOut (m_CharWidth*(2-m_LeftChar), lineCY, currentchar);	//显示地址基值

		memcpy(text,&m_text[lineBeginPos],16);	//取当前行数据
		text[16] = '\0';

		for(int l = 0; l < 16; l++)
		{
			if(text[l] < 32)
				text[l] = 46;	//不可见ASCII字符用.表示
		}
		if(lineBeginPos+16 > m_CharCount)
		{
			text[m_CharCount%16] = '\0';	//最后的数据不满一行时
		}
		
		dc.TextOut (m_TextStart, lineCY, text);//显示右面的ASCII字符

		//被选中时反色显示右面的ASCII字符
		int selStart = (m_SelStart - lineBeginPos)<0? 0:(m_SelStart - lineBeginPos);
		int selEnd = (m_SelEnd - lineBeginPos)>15? 15:(m_SelEnd - lineBeginPos);
		if(selStart <= 15 && selEnd >= 0)
		{
			dc.SetBkColor(::GetSysColor ( COLOR_HIGHLIGHT ));
			dc.SetTextColor(::GetSysColor ( COLOR_HIGHLIGHTTEXT ));
			text[selEnd+1]='\0';
			dc.TextOut (m_TextStart+selStart*m_CharWidth, lineCY, &text[selStart]);
		}
		else
		{
			dc.SetTextColor(::GetSysColor(COLOR_WINDOWTEXT));
			dc.SetBkColor(RGB(255,255,255));
		}

		for(UINT j = 0; j < 16; j++)
		{
			dwPos = j + lineBeginPos;

			if(dwPos > (m_CharCount-1))
				goto bitblt;			//显示完最后一行退出
			
			if(dwPos >= m_SelStart && dwPos <= m_SelEnd)
			{
				dc.SetBkColor(::GetSysColor ( COLOR_HIGHLIGHT ));
				dc.SetTextColor(::GetSysColor ( COLOR_HIGHLIGHTTEXT ));
			}
			else
			{
				dc.SetTextColor(::GetSysColor(COLOR_WINDOWTEXT));
				dc.SetBkColor(RGB(255,255,255));
			}

			lineCX = m_HexStart + j * m_CharWidth *3 ;				//计算当前要显示的二进制字符的位置
			sprintf(currentchar, "%02X", ((UCHAR *)m_text)[dwPos]);	
			dc.TextOut (lineCX, lineCY, currentchar);				//显示二进制字符

			if(dwPos == m_SelEnd)									//选中单个字符的显示
			{
				dc.SetTextColor(::GetSysColor(COLOR_HIGHLIGHTTEXT));
				dc.SetBkColor(RGB(255,0,0));
				UCHAR cHex = m_text[dwPos];
				if(m_bFirst)//二进制字符的高四位选中
				{
					cHex = cHex & 0xf0;
					cHex = cHex >> 4;
					sprintf(currentchar, "%X", cHex);
					dc.TextOut (lineCX, lineCY, currentchar);
				}
				else
				{
					lineCX = m_HexStart + j * m_CharWidth *3 + m_CharWidth;
					cHex = cHex & 0x0f;
					sprintf(currentchar, "%X", cHex);
					dc.TextOut (lineCX, lineCY, currentchar);
				}
			}
		}
	}

bitblt:
	pDC->BitBlt(0, 0, rc.Width(), rc.Height(), &dc, 0, 0, SRCCOPY);
	dc.DeleteDC ();
}

/////////////////////////////////////////////////////////////////////////////
// CHexEditView diagnostics

#ifdef _DEBUG
void CHexEditView::AssertValid() const
{
	CView::AssertValid();
}

void CHexEditView::Dump(CDumpContext& dc) const
{
	CView::Dump(dc);
}
#endif //_DEBUG

/////////////////////////////////////////////////////////////////////////////
// CHexEditView message handlers

void CHexEditView::SetText(char *input, int len)
{
	m_text = input;

	m_CharCount = len;
	m_Rows = m_CharCount/16;

	m_TopLine = 1;
	m_LeftChar = 0;
	m_SelStart = 0;
	m_SelEnd = 0;
	m_StartDrag = FALSE;
	m_bFirst = TRUE;

	CFont font;
	m_LineHeight = 16;
	font.CreateFont ( m_LineHeight, 0, 0, 0, FW_NORMAL, 0, 0, 0, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN, 0 );
	CFont* oldFont = GetDC()->SelectObject ( &font );
	
	CSize size = GetDC()->GetTextExtent ("A");
	m_LineHeight = size.cy;
	m_CharWidth = size.cx ;

	GetPageRowCols();
	SetVertScrollBar();
	SetHorzScrollBar();
}


void CHexEditView::OnSetFocus(CWnd* pOldWnd) 
{
	CView::OnSetFocus(pOldWnd);
	
	m_bFocused = TRUE;
}

void CHexEditView::OnKillFocus(CWnd* pNewWnd) 
{
	CView::OnKillFocus(pNewWnd);
	
	m_bFocused = FALSE;
}

void CHexEditView::OnLButtonDown(UINT nFlags, CPoint point) 
{
	CView::OnLButtonDown(nFlags, point);
	m_StartDrag = TRUE;
	m_bFirst = TRUE;

	m_oriStart = m_SelStart = m_SelEnd = Point2Pos(point);
	Invalidate(FALSE);
}

void CHexEditView::OnLButtonUp(UINT nFlags, CPoint point) 
{
	CView::OnLButtonUp(nFlags, point);
	
	if(m_StartDrag)
	{
		m_SelEnd = Point2Pos(point);
		if(m_SelEnd < m_oriStart)
		{
			m_SelStart = m_SelEnd;
			m_SelEnd = m_oriStart;
		}
		else
		{
			m_SelStart = m_oriStart;
		}
		Invalidate(FALSE);
		m_StartDrag = FALSE;
	}
}

void CHexEditView::OnMouseMove(UINT nFlags, CPoint point) 
{
	CView::OnMouseMove(nFlags, point);
	if(m_StartDrag)
	{
		m_SelEnd = Point2Pos(point);
		if(m_SelEnd < m_oriStart)	//反向选择
		{
			m_SelStart = m_SelEnd;
			m_SelEnd = m_oriStart;
		}
		else
		{
			m_SelStart = m_oriStart;
		}
		Invalidate(FALSE);
	}
}
//根据鼠标位置求鼠标当前指向的字符
UINT CHexEditView::Point2Pos(CPoint point)
{
	if(m_text == NULL)
		return 0;
	UINT line = m_TopLine + point.y / m_LineHeight - 1;//鼠标所在的行
	UINT charset;
	
	if(point.x < m_HexStart)
		charset = 0;
	else if(point.x < m_HexStart + m_CharWidth * 48)
		charset = (point.x - m_HexStart)/(m_CharWidth*3);
	else if(point.x < m_TextStart + 16 * m_CharWidth)
		charset = (point.x - m_TextStart)/m_CharWidth;
	else
		charset = 15;
	return ((line * 16 + charset)>m_CharCount?m_CharCount-1:(line * 16 + charset));
}

void CHexEditView::OnInitialUpdate() 
{
	CView::OnInitialUpdate();
}

void CHexEditView::OnSize(UINT nType, int cx, int cy) 
{
	CView::OnSize(nType, cx, cy);

	GetPageRowCols();
	SetVertScrollBar();
	SetHorzScrollBar();
}

//设置滚动条
void CHexEditView::SetVertScrollBar()
{	
	if((m_Rows - m_TopLine +  2) < m_PageRows) m_TopLine = 1;

	SCROLLINFO si;
	ZeroMemory(&si,sizeof(si));
	si.cbSize = sizeof(si);
	si.fMask = SIF_DISABLENOSCROLL | SIF_PAGE | SIF_POS | SIF_RANGE;
	si.nMin = 0;
	si.nMax = m_Rows;
	si.nPage = m_PageRows;
	si.nPos = m_TopLine-1;
	VERIFY(SetScrollInfo(SB_VERT, &si, TRUE));
	Invalidate(FALSE);
}

void CHexEditView::SetHorzScrollBar()
{
	if((80 - m_LeftChar + 2) < m_PageCols) m_LeftChar = 0;
	
	SCROLLINFO si;
	ZeroMemory(&si,sizeof(si));
	si.cbSize = sizeof(si);
	si.fMask = SIF_DISABLENOSCROLL | SIF_PAGE | SIF_POS | SIF_RANGE;
	si.nMin = 0;
	si.nMax = 80;
	si.nPage = m_PageCols;
	si.nPos = m_LeftChar;
	VERIFY(SetScrollInfo(SB_HORZ, &si, TRUE));
	Invalidate(FALSE);
}

BOOL CHexEditView::PreCreateWindow(CREATESTRUCT& cs) 
{
	CWnd *pParentWnd = CWnd::FromHandlePermanent(cs.hwndParent);
	if (pParentWnd == NULL || ! pParentWnd->IsKindOf(RUNTIME_CLASS(CSplitterWnd)))
	{
		//	View must always create its own scrollbars,
		//	if only it's not used within splitter
		cs.style |= (WS_HSCROLL | WS_VSCROLL);
	}
	cs.lpszClass = AfxRegisterWndClass(CS_DBLCLKS);	
	return CView::PreCreateWindow(cs);
}

BOOL CHexEditView::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt) 
{
	
	if(zDelta > 0)
	{
		m_TopLine = --m_TopLine < 1 ? 1 : m_TopLine;
	}
	else
	{
		if((m_TopLine + m_PageRows -2) < m_Rows)
			m_TopLine+=1;
	}
	SetVertScrollBar();
	SetHorzScrollBar();
	return CView::OnMouseWheel(nFlags, zDelta, pt);
}

//计算一页能够显示的字符的行数和列数
void CHexEditView::GetPageRowCols()
{
	CRect rc;
	GetClientRect(rc);
	m_PageRows =  rc.Height ()/m_LineHeight;
	m_PageCols = rc.Width ()/m_CharWidth;
}

//处理滚动条消息
void CHexEditView::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) 
{
	CView::OnHScroll(nSBCode, nPos, pScrollBar);

	SCROLLINFO si;
	si.cbSize = sizeof(si);
	si.fMask = SIF_ALL;
	VERIFY(GetScrollInfo(SB_HORZ, &si));

	switch (nSBCode)
	{
	case SB_LEFT:
		m_LeftChar = 0;
		break;
	case SB_BOTTOM:
		m_LeftChar = 80 - m_PageCols + 1;
		break;
	case SB_LINEUP:
		m_LeftChar = m_LeftChar - 1;
		break;
	case SB_LINEDOWN:
		m_LeftChar = m_LeftChar + 1;
		break;
	case SB_PAGEUP:
		m_LeftChar = m_LeftChar - si.nPage + 1;
		break;
	case SB_PAGEDOWN:
		m_LeftChar = m_LeftChar + si.nPage - 1;
		break;
	case SB_THUMBPOSITION:
	case SB_THUMBTRACK:
		m_LeftChar = si.nTrackPos;
		break;
	default:
		return;
	}

	if((m_LeftChar + m_PageCols - 2) > 80) m_LeftChar = 80 - m_PageCols +2;
	if(m_LeftChar < 0) m_LeftChar = 0;

	SetHorzScrollBar();
}

void CHexEditView::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) 
{
	CView::OnVScroll(nSBCode, nPos, pScrollBar);

	SCROLLINFO si;
	si.cbSize = sizeof(si);
	si.fMask = SIF_ALL;
	VERIFY(GetScrollInfo(SB_VERT, &si));

	switch (nSBCode)
	{
	case SB_TOP:
		m_TopLine = 0;
		break;
	case SB_BOTTOM:
		m_TopLine = m_Rows  - m_PageRows + 1;
		break;
	case SB_LINEUP:
		m_TopLine = m_TopLine - 1;
		break;
	case SB_LINEDOWN:
		m_TopLine = m_TopLine + 1;
		break;
	case SB_PAGEUP:
		m_TopLine = m_TopLine - si.nPage + 1;
		break;
	case SB_PAGEDOWN:
		m_TopLine = m_TopLine + si.nPage - 1;
		break;
	case SB_THUMBPOSITION:
	case SB_THUMBTRACK:
		m_TopLine = si.nTrackPos+1;
		break;
	default:
		return;
	}

	if((m_TopLine + m_PageRows -2) > m_Rows) m_TopLine = m_Rows - m_PageRows + 2;
	if(m_TopLine < 1) m_TopLine = 1;

	SetVertScrollBar();
}

//输入字符转换成二进制数据
void CHexEditView::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags) 
{
	CView::OnChar(nChar, nRepCnt, nFlags);
	UINT input;
	UCHAR cHex = m_text[m_SelEnd];
	
	if(nChar > 47 && nChar < 58)
	{
		input = nChar - 48;
	}
	else if (nChar > 64 && nChar < 71)
	{
		input = nChar - 64 + 9;
	}
	else if (nChar > 96 && nChar < 103)
	{
		input = nChar - 96 + 9;
	}
	else
	{
		return;
	}
	
	if(m_bFirst)
	{
		input = input << 4;
		cHex = cHex & 0x0f;
		cHex = cHex | input;
		m_bFirst = FALSE;
		m_text[m_SelEnd] = cHex;
	}
	else
	{
		cHex = cHex & 0xf0;
		cHex = cHex | input;
		m_bFirst = TRUE;
		m_text[m_SelEnd] = cHex;
		m_SelEnd ++;
	}
	if(m_SelEnd == m_CharCount)
	{
		m_CharCount = m_SelEnd + 1;
		m_Rows = m_CharCount/16;
	}
	m_text = ((CMyDoc*)GetDocument ())->JudgeMem (m_CharCount + 100);
	m_SelStart = m_SelEnd;
	ChangeTop();
	ChangeLeft();
	Invalidate(FALSE);
}

//键盘的上下左右键处理
BOOL CHexEditView::PreTranslateMessage(MSG* pMsg)
{
	if(pMsg->message == WM_KEYDOWN)
	{
		switch (LOWORD(pMsg->wParam))
		{
		case VK_LEFT:
			OnCharLeft();
			break;
		case VK_RIGHT:
			OnCharRight();
			break;
		case VK_UP:
			OnLineUp();
			break;
		case VK_DOWN:
			OnLineDown();
			break;
		default:
			break;
		}
	}
	return CView::PreTranslateMessage(pMsg);
}

void CHexEditView::OnCharLeft()
{
	if(m_bFirst && m_SelEnd > 0)
	{
		m_SelEnd --;
		m_bFirst = FALSE;
	}
	else
	{
		m_bFirst = TRUE;
	}
	ChangeTop();
	ChangeLeft();
	m_SelStart = m_SelEnd;
	Invalidate(FALSE);
}

void CHexEditView::OnCharRight()
{
	if(m_bFirst)
	{
		m_bFirst = FALSE;
	}
	else if( m_SelEnd < m_CharCount-1)
	{
		m_bFirst = TRUE;
		m_SelEnd++;
	}
	ChangeTop();
	ChangeLeft();
	m_SelStart = m_SelEnd;
	Invalidate(FALSE);
}

void CHexEditView::OnLineUp()
{
	if(m_SelEnd > 15)
		m_SelEnd = m_SelEnd - 16;

	ChangeTop();
	ChangeLeft();
	m_SelStart = m_SelEnd;
	Invalidate(FALSE);
}

void CHexEditView::OnLineDown()
{
	if(m_SelEnd + 16 < m_CharCount)
		m_SelEnd = m_SelEnd + 16;
	else
		m_SelEnd = m_CharCount-1;
	ChangeTop();
	ChangeLeft();
	m_SelStart = m_SelEnd;
	Invalidate(FALSE);
}

//计算顶行
void CHexEditView::ChangeTop()
{
	int newtop = m_TopLine;

	if((m_SelEnd/16 + 1) < m_TopLine)
	{
		newtop = m_SelEnd/16 + 1;
	}

	if((m_SelEnd/16 + 2) > m_TopLine+m_PageRows)
	{
		newtop = m_SelEnd/16 + 2 - m_PageRows;
	}

	if(newtop != m_TopLine)
	{
		m_TopLine = newtop;
		SetVertScrollBar();
	}
}

//计算左列
void CHexEditView::ChangeLeft()
{
	int currentcol = m_SelEnd%16;
	if(currentcol*3 + 14 < m_LeftChar)
	{
		m_LeftChar = currentcol*3 + 14;
		SetHorzScrollBar();
	}
	if(currentcol*3 + 14 - m_LeftChar+1 > m_PageCols)
	{
		m_LeftChar = currentcol*3 + 14 - m_PageCols +2;
		SetHorzScrollBar();
	}
}